package com.example.vulnerableapplication.provider;

import android.content.ContentProvider;
import android.content.ContentValues;
import android.content.Context;
import android.content.UriMatcher;
import android.content.pm.ProviderInfo;
import android.content.res.AssetFileDescriptor;
import android.content.res.AssetManager;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.os.CancellationSignal;
import android.os.ParcelFileDescriptor;
import android.util.Log;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;

public class MyContentProvider extends ContentProvider {

    //这里的AUTHORITY就是我们在AndroidManifest.xml中配置的authorities，这里的authorities可以随便写
    private static final String AUTHORITY = "com.example.student";
    //匹配成功后的匹配码
    private static final int MATCH_ALL_CODE = 1;
    private static final int MATCH_ONE_CODE = 2;

    private static final Uri NOTIFY_URI = Uri.parse("content://" + AUTHORITY + "/student");


    private static final UriMatcher uriMatcher;

    //在静态代码块中添加要匹配的 Uri
    static {
        //匹配不成功返回NO_MATCH(-1)
        uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
        /**
         * uriMatcher.addURI(authority, path, code); 其中
         * authority：主机名(用于唯一标示一个ContentProvider,这个需要和清单文件中的authorities属性相同)
         * path:路径路径(可以用来表示我们要操作的数据，路径的构建应根据业务而定)
         * code:返回值(用于匹配uri的时候，作为匹配成功的返回值)
         */
        uriMatcher.addURI(AUTHORITY, "student", MATCH_ALL_CODE);// 匹配记录集合
        uriMatcher.addURI(AUTHORITY, "student/#", MATCH_ONE_CODE);// 匹配单条记录
    }

    @Override
    public void attachInfo(Context context, ProviderInfo info) {
        Log.e("Rzx","provider attachInfo");
        super.attachInfo(context, info);
    }

    @Override
    public boolean onCreate() {
        Log.e("Rzx","provider oncreate");
        return false;
    }

    @Nullable
    @Override
    public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection, @Nullable String[] selectionArgs, @Nullable String sortOrder) {
        switch (uriMatcher.match(uri)) {
            /**
             * 这里如果匹配是uriMatcher.addURI(AUTHORITY, "student",
             * MATCH_SUCCESS_CODE);中的Uri,则查询全部
             *
             */
            case MATCH_ALL_CODE:
                Log.d("mmm", "queryAll");
                break;
            /**
             * 这里如果匹配是uriMatcher.addURI(AUTHORITY,
             * "student/#",MATCH_ONE_CODE);中的Uri，查询一个
             */
            case MATCH_ONE_CODE:

                break;
            default:
        }
        return null;
    }

    @Nullable
    @Override
    public String getType(@NonNull Uri uri) {
        return null;
    }

    /**
     * 插入 使用UriMatch的实例中的match方法对传过来的 Uri进行匹配。 这里通过ContentResolver传过来一个Uri，
     * 用这个传过来的Uri跟在ContentProvider中静态代码块中uriMatcher.addURI加入的Uri进行匹配
     * 根据匹配的是否成功会返回相应的值，在上述静态代码块中调用uriMatcher.addURI(AUTHORITY,
     * "student",MATCH_CODE)这里的MATCH_CODE
     * 就是匹配成功的返回值，也就是说假如返回了MATCH_CODE就表示这个Uri匹配成功了
     * ，我们就可以按照我们的需求就行操作了,这里uriMatcher.addURI(AUTHORITY,
     * "person/data",MATCH_CODE)加入的Uri为：
     * content://com.example.studentProvider/student
     * ，如果传过来的Uri跟这个Uri能够匹配成功，就会按照我们设定的步骤去执行相应的操作
     */
    @Nullable
    @Override
    public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) {
        switch (uriMatcher.match(uri)) {
            case MATCH_ALL_CODE:
                String aaa = (String) values.get("aaa");
                Log.d("mmm", "insertAll" + aaa);
                //通知ContentObserver数据发生变化了
                notifyDataChanged();
                break;
            case MATCH_ONE_CODE:
                break;
            default:
        }
        return null;
    }

    @Override
    public int delete(@NonNull Uri uri, @Nullable String selection, @Nullable String[] selectionArgs) {
        switch (uriMatcher.match(uri)) {
            case MATCH_ALL_CODE:
                Log.d("mmm", "deleteAll");
                break;
            case MATCH_ONE_CODE:
                break;
            default:
        }
        return 0;
    }

    @Override
    public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection, @Nullable String[] selectionArgs) {
        switch (uriMatcher.match(uri)) {
            case MATCH_ALL_CODE:
                Log.d("mmm", "updateAll");
                break;
            case MATCH_ONE_CODE:
                break;
            default:
        }
        return 0;
    }

    //通知指定URI数据已改变
    private void notifyDataChanged() {
        getContext().getContentResolver().notifyChange(NOTIFY_URI, null);
    }


    @Override
    public ParcelFileDescriptor openFile(Uri uri, String mode)
            throws FileNotFoundException {
        Log.e("Rzx","provider openfile");
        Log.e("Rzx",uri.toString()+uri.getPath());
        //由于是应用内的不同进程，故这里把文件放到data/data/包名 目录下
        File testFile =new File(getContext().getCacheDir(),"test.html");

        // ParcelFileDescriptor.MODE_READ_ONLY：只可读
        // ParcelFileDescriptor.MODE_WRITE_ONLY：只可写
        // ParcelFileDescriptor.MODE_READ_WRITE：可读可写
        return ParcelFileDescriptor.open(testFile,
                ParcelFileDescriptor.MODE_READ_WRITE);

    }
    @Override
    public AssetFileDescriptor openAssetFile(Uri uri,  String mode) throws FileNotFoundException {
/*        String path = uri.getPath();
        Log.e("Rzx","provider openAssetFile:"+uri);
        try {
//            AssetFileDescriptor assetManager = getContext().getAssets().openFd("test.html");

            File testFile =new File(getContext().getCacheDir(),"test.html");
            FileOutputStream fos = new FileOutputStream(testFile);
            AssetFileDescriptor.

            if(path.equals("out")){
                Log.e("Rzx","provider openAssetFile write file:");
                return assetManager;
            }else{
                return assetManager;
            }

        } catch (IOException e) {
            e.printStackTrace();
        }


        return null;*/
        return super.openAssetFile(uri, mode);
    }

    @Override
    public Bundle call(String method, String arg, Bundle extras) {

        Log.e("Rzx","provider call "+ method+ arg);
        return null;
    }


}